package mop.controller;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import mop.exception.BusinessRule1Exception;
import mop.exception.BusinessRule3Exception;
import mop.exception.IllegalDependencyException;
import mop.exception.IllegalDuplicationException;
import mop.exception.IllegalFieldException;
import mop.exception.IllegalIdException;
import mop.exception.IllegalValueException;
import mop.exception.InsufficientPermissionException;
import mop.model.World;
import mop.model.project.Project;
import mop.model.project.ProjectInterface;
import mop.model.resource.ResourceInterface;
import mop.model.task.Task;
import mop.model.task.TaskInterface;
import mop.model.task.tasktype.TaskType;
import mop.model.task.tasktype.TaskTypeInterface;

/**
 * CreateTaskController
 * 
 * Use case controller for the creation of a new task 
 * (use case 1)
 * 
 * @author	MOP Team 7
 */
public class CreateTaskController extends UseCaseController
{

	
	/**
	 * @see UseCaseController#UseCaseController(World)
	 */
	public CreateTaskController(World world)
	{
		super(world);
	}
	
	/**
	 * Return a list with all possible dependencies
	 * TODO relocate source ? -> if so, also do this in modify task details controller
	 * @return a list of interfaces to all tasks in system
	 */
	public List<TaskInterface> getPossibleDependencies()
	{
		return getAllTasks();
	}
	
	/**
	 * Return a list with all possible resources
	 * TODO relocate source ?-> if so, also do this in modify task details controller
	 * @return a list of interfaces to resources
	 */
	public List<ResourceInterface> getPossibleResources()
	{
		return getAllResources();
	}
	
	/**
	 * Return a list of interfaces of all existing tasktypes
	 * 
	 * @return List<TaskType>
	 */
	public List<TaskTypeInterface> getTaskTypes()
	{
		List<TaskType> base = super.getWorld().getTaskTypeDataBase().fetchAll();
		if(base == null) return null;
		
		List<TaskTypeInterface> ret = new LinkedList<TaskTypeInterface>();
		for(TaskType t : base)
		{
			ret.add(t);
		}
		return ret;
	}

        /**
         * Checks whether the current user can create a task of the given tasktype.
         *
         * @param   String taskTypeId
         * @return  boolean
         * @throws  InsufficientPermissionException
         *          If the current user cannot create a task of the given tasktype.
         */
        public boolean canCreateTaskType(String taskTypeId) throws InsufficientPermissionException
        {
            try {
                TaskType tt = getWorld().getTaskTypeDataBase().find(taskTypeId);
                if (tt.checkUserConstraints(getWorld().getCurrentUser()))
                    return true;
                else
                    throw new InsufficientPermissionException("User with type "+getWorld().getCurrentUser().getUserType()+" can not create task of type "+tt);
            } catch (IllegalIdException e) {
                return false;
            }
        }
	
	/**
	 * CreateTask method
	 * 
	 * @param id			The identifier for the task
	 * @param tt			The tasktypeInterface for the task
	 * @param start			The start time of the task
	 * @param dur			The duration of the task
	 * @param deadline		The deadline of the task
	 * @param dependencies	The dependencies needed by the task
	 * 
	 * @throws IllegalIdException
	 * 		| @see convertFromIdToList @see getTaskList
	 * @throws IllegalDependencyException 
	 * 		| @see Task constructor
	 * @throws IllegalDeadlineException 
	 * 		| @see Schedule Constructor
	 * @throws IllegalDuplicationException
	 * 		| @see User#addTask(Task)
	 * @throws BusinessRule1Exception 
	 * 		| @see Schedule#setDates(Timestamp, Timestamp, Timestamp)
	 * @throws BusinessRule3Exception 
	 * 		| @see //TODO: set this to the correct place
	 * @throws IllegalFieldException 
	 * @throws IllegalValueException 
	 * @throws InsufficientPermissionException 
	 */
	public TaskInterface createTask(String id,TaskTypeInterface tt,HashMap<String,String> fields,Timestamp start,Timestamp dur,Timestamp deadline,List<String> dependencies)
                throws IllegalIdException, IllegalDependencyException, IllegalDuplicationException, BusinessRule3Exception, BusinessRule1Exception, IllegalValueException, IllegalFieldException, InsufficientPermissionException
	{
		List<Task> tasklist = getTaskList(dependencies);
		TaskType tat = super.getWorld().getTaskTypeDataBase().find(tt.getId());
		Task nt = new Task(id,tat,fields,start,dur,deadline,tasklist,getWorld().getCurrentUser());
		return nt;
	}
	
	/***************************************************************************
	 * 					Assign task to project
	 ***************************************************************************/
	  /**
     * @see UseCaseController#getAllProjects()
     */
    public List<ProjectInterface> getProjectList()
    {
            return super.getAllProjects();
    }
	
    /**
     * Assigns a task to a project (and replaces old assignment if necessary).
     * 
     * @param       task	The id of a Task.
     * @param       project	The id of a Project.
     * 
     * @effect      Sets the project assignment in the given task.
     *       | task.setProject(project)
     * @effect      Adds the task to the project.
     *       | project.addTask(task)
     * @throws      IllegalIdException
     *       Thrown when the task or project description is invalid, or does not exist.
     */
	public void assignTaskToProject(String id, String project) 
		throws IllegalIdException
	{
	    // find corresponding task and project
        Task t = super.getTask(id);
        Project p = super.getWorld().getProjectDataBase().find(project);
        
        // set project assignment in the task
        t.setProject(p);
	}
	
	
	/***************************************************************************
	 * 								Visit
	 ***************************************************************************/
	
	/**
	 * Make a CallBack to the visitor
	 * @param v the visitor
	 */
	public void accept(ControllerVisitor v)
	{
		v.visit(this);
	}
	
	/***************************************************************************
	 * 								Acl
	 ***************************************************************************/
	
	@Override
	public String getAssetId() {
		return "CreateTask";
	}
	
}